

#include "bsp.h"
#include "bsp_oled.h"
#include "oledfont.h"




	
#define OLED_CMD  0	//
#define OLED_DATA 1	//
#define OLED_MODE 0
	
	
#define SIZE 16
#define XLevelL		0x02
#define XLevelH		0x10
#define Max_Column	128
#define Max_Row		64
#define	Brightness	0xFF 
#define X_WIDTH 	128
#define Y_WIDTH 	64	 
#define OLED_W   	X_WIDTH
#define OLED_H		Y_WIDTH		
#define GRAM_H 		OLED_H/8
//uint8_t OLED_GRAM[OLED_W][GRAM_H]; // 缓存区



void oledWriteByte(u8 dat, u8 cmd)
{
	if (cmd)
	{
		OLED_DC_SET();
	}
	else if (cmd != 1)
	{
		OLED_DC_CLR();
	}
	
    DISABLE_INT();
    OLED_CS_CLR();	
	bsp_spiWrite0(dat);
	OLED_CS_SET();
    ENABLE_INT();
	OLED_DC_SET();
}

void oled_SetPos(unsigned char x, unsigned char y)
{
	oledWriteByte(0xb0 + y, OLED_CMD);
	oledWriteByte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);
	oledWriteByte((x & 0x0f) , OLED_CMD);
}

void oled_DisplayOn(void)
{
	oledWriteByte(0X8D, OLED_CMD); // SET DCDC
	oledWriteByte(0X14, OLED_CMD); // DCDC ON
	oledWriteByte(0XAF, OLED_CMD); // DISPLAY ON
}

void oled_DisplayOff(void)
{
	oledWriteByte(0X8D, OLED_CMD); // SET DCDC
	oledWriteByte(0X10, OLED_CMD); // DCDC OFF
	oledWriteByte(0XAE, OLED_CMD); // DISPLAY OFF
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!	
void oled_Clear(void)
{
	u8 i, n;
	for (i = 0; i < 8; i++)
	{
		oledWriteByte(0xb0 + i, OLED_CMD); //设置页地址（0~7）
		oledWriteByte(0x00, OLED_CMD);	  //设置显示位置—列低地址
		oledWriteByte(0x10, OLED_CMD);	  //设置显示位置—列高地址   
		for (n = 0; n < 128; n++)
			oledWriteByte(0x00, OLED_DATA);
	}//更新显示
}

//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~8
//mode:0,反白显示;1,正常显示				 
//size:选择字体 16/8

void oled_ShowChar(u8 x, u8 y, u8 chr)
{
	unsigned char c = 0, i = 0;
	c = chr - ' '; //得到偏移后的值	
	if (x > Max_Column - 1)
	{
		x = 0;
		y = y + 2;
	}
	if (SIZE == 16)
	{
		oled_SetPos(x, y);
		for (i = 0; i < 8; i++)
			oledWriteByte(F8X16[c * 16 + i], OLED_DATA);
		oled_SetPos(x, y + 1);
		for (i = 0; i < 8; i++)
			oledWriteByte(F8X16[c * 16 + i + 8], OLED_DATA);
	}
	else
	{
		oled_SetPos(x, y + 1);
		for (i = 0; i < 6; i++){
		   // oledSetPos(x+i, y + 1);
			oledWriteByte(F6x8[c][i], OLED_DATA);
		}
	}

}
//m^n函数
u32 oled_pow(u8 m, u8 n)
{
	u32 result = 1;
	while (n--)
		result *= m;
	return result;
}
//显示2个数字
//x,y :起点坐标	 
//len :数字的位数
//size:字体大小
//mode:模式	0,填充模式;1,叠加模式
//num:数值(0~4294967295);	

void oled_ShowNum(u8 x, u8 y, u32 num, u8 len, u8 size2)
{
	u8 t, temp;
	u8 enshow = 0;
	for (t = 0; t < len; t++)
	{
		temp = (num / oled_pow(10, len - t - 1)) % 10;
		if (enshow == 0 && t < (len - 1))
		{
			if (temp == 0)
			{
				oled_ShowChar(x + (size2 / 2) * t, y, ' ');
				continue;
			}
			else
				enshow = 1;
		}
		oled_ShowChar(x + (size2 / 2) * t, y, temp + '0');
	}
}

void oled_ShowString(u8 x, u8 y, u8 *chr)//(0,0."hello world")
{
	unsigned char j = 0;
	while (chr[j] != '\0')
	{
		oled_ShowChar(x, y, chr[j]);
		x += 8;
		if (x > 120)
		{
			x = 0;
			y += 2;
		}
		j++;
	}
}


void oled_ShowCHinese(u8 x, u8 y, u8 no)
{
	u8 t, adder = 0;
	oled_SetPos(x, y);
	for (t = 0; t < 16; t++)
	{
		oledWriteByte(Hzk[2 * no][t], OLED_DATA);
		adder += 1;
	}
	oled_SetPos(x, y + 1);
	for (t = 0; t < 16; t++)
	{
		oledWriteByte(Hzk[2 * no + 1][t], OLED_DATA);
		adder += 1;
	}
}

//oledShowCHStr(0,0,"我们嵌入式");
void oled_ShowCHStr(unsigned char X , unsigned char Y, unsigned char *pstr)
{
	unsigned char i;
	unsigned char Addr = 0;
	unsigned char count = 0;

	while(*pstr)
	{
		for(i=0; i<chinese_12_len; i++)    //在字库中根据汉字GBK内码寻找汉字的字模
		{
			if((*pstr == chinese_12[i].value[0])&&(*(pstr+1) == chinese_12[i].value[1])&&(*(pstr+2) == chinese_12[i].value[2]))
			{
				Addr = i;                      //Addr 汉字在字库中的下标
				break;
			}				
		}		
		oled_SetPos(X+count*12,Y);                             //设置初始位置
		for (i=0; i<12; i++)              //写上半部分
		{ 	
			oledWriteByte(chinese_12[Addr].data[i],1);
		}
		oled_SetPos(X+count*12,Y+1);    
		for (i=0; i<12; i++)              //写一个汉字
		{ 	
			oledWriteByte(chinese_12[Addr].data[12+i],1);
		}
		count++;                          //已显示的字数	
		pstr = pstr+3;
	}	  
}

void oled_DrawBMP(unsigned char xs, unsigned char ys, unsigned char xw, unsigned char yh, const unsigned char BMP[])
{
	unsigned int j = 0;
	unsigned char x, y, yend;

	if (yh % 8 == 0)
		yend = ys + yh / 8;
	else
		yend = ys + yh / 8 + 1;
	for (y = ys; y < yend; y++)
	{
		oled_SetPos(xs, y);
		for (x = xs; x < xs + xw; x++)
		{
			oledWriteByte(BMP[j++], OLED_DATA);
		}
	}
}


void OLED_gpioInit(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	/* 打开GPIO时钟 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE);


	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	/* 推挽输出模式 */	
	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
	GPIO_Init(GPIOD, &GPIO_InitStructure);
}

void oled_Init(void)
{	
	
	OLED_gpioInit();
	
	oledWriteByte(0xAE, OLED_CMD); //--turn off oled panel
	oledWriteByte(0x00, OLED_CMD); //---set low column address
	oledWriteByte(0x10, OLED_CMD); //---set high column address
	oledWriteByte(0x40, OLED_CMD); //--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
	oledWriteByte(0x81, OLED_CMD); //--set contrast control register
	oledWriteByte(0xCF, OLED_CMD); // Set SEG Output Current Brightness
	oledWriteByte(0xA1, OLED_CMD); //--Set SEG/Column Mapping      0xa0左右反置 0xa1正常
	oledWriteByte(0xC8, OLED_CMD); // Set COM/Row Scan Direction    0xc0上下反置 0xc8正常
	oledWriteByte(0xA6, OLED_CMD); //--set normal display
	oledWriteByte(0xA8, OLED_CMD); //--set multiplex ratio(1 to 64)
	oledWriteByte(0x3f, OLED_CMD); //--1/64 duty
	oledWriteByte(0xD3, OLED_CMD); //-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
	oledWriteByte(0x00, OLED_CMD); //-not offset
	oledWriteByte(0xd5, OLED_CMD); //--set display clock divide ratio/oscillator frequency
	oledWriteByte(0x80, OLED_CMD); //--set divide ratio, Set Clock as 100 Frames/Sec
	oledWriteByte(0xD9, OLED_CMD); //--set pre-charge period
	oledWriteByte(0xF1, OLED_CMD); // Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
	oledWriteByte(0xDA, OLED_CMD); //--set com pins hardware configuration
	oledWriteByte(0x12, OLED_CMD);
	oledWriteByte(0xDB, OLED_CMD); //--set vcomh
	oledWriteByte(0x40, OLED_CMD); // Set VCOM Deselect Level
	oledWriteByte(0x20, OLED_CMD); //-Set Page Addressing Mode (0x00/0x01/0x02)
	oledWriteByte(0x02, OLED_CMD); //
	oledWriteByte(0x8D, OLED_CMD); //--set Charge Pump enable/disable
	oledWriteByte(0x14, OLED_CMD); //--set(0x10) disable
	oledWriteByte(0xA4, OLED_CMD); // Disable Entire Display On (0xa4/0xa5)
	oledWriteByte(0xA6, OLED_CMD); // Disable Inverse Display On (0xa6/a7)
	oledWriteByte(0xAF, OLED_CMD); //--turn on oled panel

	oledWriteByte(0xAF, OLED_CMD); /*display ON*/
	oled_Clear();
	oled_SetPos(0, 0);
}

u8 OLED_GRAM[OLED_W][GRAM_H];



//void oled_DrawPoint(u8 x,u8 y,u8 t)
//{
//	u8 i,m,n;
//	i=y/8;
//	m=y%8;
//	n=1<<m;
//	if(t){OLED_GRAM[x][i]|=n;}
//	else
//	{
//		OLED_GRAM[x][i]=~OLED_GRAM[x][i];
//		OLED_GRAM[x][i]|=n;
//		OLED_GRAM[x][i]=~OLED_GRAM[x][i];
//	}
//}

void OLED_DrawRectangle(int16_t X, int16_t Y, uint8_t Width, uint8_t Height, uint8_t IsFilled) {
    // 确保矩形的坐标是有效的
    if (Width == 0 || Height == 0) return;

    // 绘制边界
    for (uint8_t i = 0; i < Width; i++) {
        oled_DrawPoint(X + i, Y, 1);              // 上边界
        oled_DrawPoint(X + i, Y + Height - 1, 1); // 下边界
    }
    for (uint8_t j = 0; j < Height; j++) {
        oled_DrawPoint(X, Y + j, 1);              // 左边界
        oled_DrawPoint(X + Width - 1, Y + j, 1); // 右边界
    }

    // 填充矩形
    if (IsFilled) {
        for (uint8_t y = Y + 1; y < Y + Height - 1; y++) {
            for (uint8_t x = X + 1; x < X + Width - 1; x++) {
                oled_DrawPoint(x, y, 1); // 填充点
            }
        }
    }
}

void oled_DrawPoint(int16_t X, int16_t Y, uint8_t IsFilled) {
    if (X >= 0 && X <= 127 && Y >= 0 && Y <= 63) { // 确保在屏幕范围内
        uint8_t i = Y / 8; // 计算页
        uint8_t m = Y % 8; // 计算位
        uint8_t n = 1 << m; // 计算位掩码

        if (IsFilled) {
            OLED_GRAM[X][i] |= n; // 设置点
        } else {
            OLED_GRAM[X][i] &= ~n; // 清除点
        }
    }
}





void oled_Refresh(void){
	u8 i, n;
	for (i = 0; i < OLED_H/8; i++)
	{
		oledWriteByte(0xb0 + i, OLED_CMD); 
		oledWriteByte(0x00, OLED_CMD);	  
		oledWriteByte(0x10, OLED_CMD);	  
		for (n = 0; n < OLED_W; n++)
			oledWriteByte(OLED_GRAM[n][i], OLED_DATA);
	}

}





void OLED_DrawLine(u8 x0, u8 y0, u8 x1, u8 y1, u8 t) {
    int dx = x1 - x0;
    int dy = y1 - y0;
    int sx = (dx > 0) ? 1 : (dx < 0) ? -1 : 0; // x方向增量
    int sy = (dy > 0) ? 1 : (dy < 0) ? -1 : 0; // y方向增量
    dx = abs(dx); // 取绝对值
    dy = abs(dy); // 取绝对值

    if (dx > dy) {
        int err = dx / 2;
        while (x0 != x1) {
            oled_DrawPoint(x0, y0, t); // 使用 t 参数
            err -= dy;
            if (err < 0) {
                y0 += sy;
                err += dx;
            }
            x0 += sx;
        }
    } else {
        int err = dy / 2;
        while (y0 != y1) {
            oled_DrawPoint(x0, y0, t); // 使用 t 参数
            err -= dx;
            if (err < 0) {
                x0 += sx;
                err += dy;
            }
            y0 += sy;
        }
    }
    oled_DrawPoint(x1, y1, t); // 确保绘制终点
}




//void OLED_DrawRectangle(u8 x0, u8 y0, u8 x1, u8 y1)
//{
//    // 确保 x0, y0 是左上角，x1, y1 是右下角
//    if (x0 > x1) {
//        u8 temp = x0;
//        x0 = x1;
//        x1 = temp;
//    }
//    if (y0 > y1) {
//        u8 temp = y0;
//        y0 = y1;
//        y1 = temp;
//    }

//    // 遍历 y 轴，从 y0 到 y1
//    for (u8 y = y0; y <= y1; y++) {
//        // 遍历 x 轴，从 x0 到 x1
//        for (u8 x = x0; x <= x1; x++) {
//            oled_DrawPoint(x, y, 1); // 绘制点
//        }
//    }
//}

//void OLED_DrawRectangle(u8 x0, u8 y0, u8 x1, u8 y1, u8 t) {
//    // 确保 x0, y0 是左上角，x1, y1 是右下角
//    if (x0 > x1) {
//        u8 temp = x0;
//        x0 = x1;
//        x1 = temp;
//    }
//    if (y0 > y1) {
//        u8 temp = y0;
//        y0 = y1;
//        y1 = temp;
//    }

//    // 遍历 y 轴，从 y0 到 y1
//    for (u8 y = y0; y <= y1; y++) {
//        // 遍历 x 轴，从 x0 到 x1
//        for (u8 x = x0; x <= x1; x++) {
//            oled_DrawPoint(x, y, t); // 使用 t 参数
//        }
//    }
//}


void OLED_Update(void)
{
    uint8_t page, column;

    for (page = 0; page < 8; page++) // OLED 通常有 8 页
    {
        // 设置光标到正确的页和列
        oled_SetPos(0, page); // y 轴是页，x 轴从 0 开始
        
        // 发送当前页的数据到 OLED
        for (column = 0; column < OLED_W; column++) // OLED_W 是宽度
        {
            oledWriteByte(OLED_GRAM[column][page], OLED_DATA);
        }
    }
}


void OLED_ClearArea(uint8_t x, uint8_t y, uint8_t width, uint8_t height)
{
    for (uint8_t i = 0; i < height; i++)
    {
        for (uint8_t j = 0; j < width; j++)
        {
            oled_DrawPoint(x + j, y + i, 0); // 设置为0表示清除
        }
    }
}
void Clear_OLED_GRAM() {
    for (int x = 0; x < OLED_W; x++) {
        for (int i = 0; i < GRAM_H; i++) {
            OLED_GRAM[x][i] = 0; // 将每个点清零
        }
    }
}


